# -*- coding: utf-8 -*-
import hashlib
import json
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError
from common.utils.tz import utc_to_local

_LOGGER = track_logging.getLogger(__name__)

_GATEWAY = 'http://pay.ruyipayment.com/gateway/?merId={}&merOrdId={}&merOrdAmt={}&payType={}&bankCode={}&remark={}&returnUrl={}&notifyUrl={}&signType=MD5&signMsg={}'
_QUERY_GATEWAY = 'http://pay.ruyipayment.com/query/?merId={}&merOrdId={}&signType={}&timeStamp={}&signMsg={}'

APP_CONF = {
    '990020103': {
        'API_KEY': 'ztNX8Fs5C5pDm2cm2pmjpKPbeJF5WPHk'
    },
    '990020187': {
        'API_KEY': 'tJ5KJH6Siy2RHzZjsm725kZYBtd5wr5f'
    },
}


def _get_api_key(mch_id):
    return APP_CONF[mch_id]['API_KEY']


def generate_sign(parameter, key):
    '''  生成下单签名 '''
    s = 'merId={}&merOrdId={}&merOrdAmt={}&payType={}&bankCode={}&remark={}&returnUrl={}&notifyUrl={}&signType=MD5&merKey={}'.format(
        parameter['merId'], parameter['merOrdId'], parameter['merOrdAmt'],
        parameter['payType'], parameter['bankCode'], parameter['remark'],
        parameter['returnUrl'], parameter['notifyUrl'], key)
    m = hashlib.md5()
    m.update(s.encode('utf-8'))
    sign = m.hexdigest()
    _LOGGER.info(u'ruyipay origin string: %s, sign:%s', s, sign)
    return sign


def generate_query_sign(parameter, key):
    '''  生成查询签名 '''
    s = 'merId={}&timeStamp={}&merOrdId={}&signType=MD5&merKey={}'.format(
        parameter['merId'], parameter['timeStamp'], parameter['merOrdId'], key)
    m = hashlib.md5()
    m.update(s.encode('utf-8'))
    sign = m.hexdigest()
    _LOGGER.info(u'ruyipay origin string: %s, sign:%s', s, sign)
    return sign


def verify_notify_sign(params, key):
    sign = params['signMsg']
    params.pop('signMsg')
    s = 'merId={}&merOrdId={}&merOrdAmt={}&sysOrdId={}&tradeStatus={}&remark={}&signType={}&merKey={}'.format(
        params['merId'], params['merOrdId'], params['merOrdAmt'], params['sysOrdId'], params['tradeStatus'],
        params['remark'], params['signType'], key)
    m = hashlib.md5()
    m.update(s.encode('utf-8'))
    calculated_sign = m.hexdigest()
    if sign != calculated_sign:
        _LOGGER.info("ruyipay sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % params)


def verify_query_sign(params, key):
    sign = params['signMsg']
    params.pop('signMsg')
    s = 'merOrdId={}&merOrdAmt={}&merId={}&sysOrdId={}&tradeStatus={}&merKey={}'.format(
        params['merOrdId'], params['merOrdAmt'], params['merId'], params['sysOrdId'], params['tradeStatus'],
        key)
    m = hashlib.md5()
    m.update(s.encode('utf-8'))
    calculated_sign = m.hexdigest()
    if sign != calculated_sign:
        _LOGGER.info("ruyipay sign: %s, calculated sign: %s", sign, calculated_sign)
        raise ParamError('sign not pass, data: %s' % params)


# 10-网关支付 20-快捷支付 30-微信扫码支付 31-微信WAP支付 40-支付宝扫码支付
# 41-支付宝WAP支付 50-QQ钱包扫码支付 51-QQ钱包WAP支付 60-京东钱包扫码支付 61-京东钱包 WAP 支付 11-银联扫码支付

# WECHATQR 微信扫码
# WECHATWAP
# 微信WAP
#
# ALIPAYWAP
# 支付宝WAP
#
# QQWALLET
# QQ钱包扫码
#
# QQWAP
# QQ钱包WAP
#
# JDWAP
# 京东钱包WAP
#
# QUICK
# 快捷支付
def _get_paytype_and_bankcode(pay_type):
    if pay_type == 'wxpay':
        return "WECHATWAP", '31'
    elif pay_type == 'qq':
        return "QQWAP", '51'
    elif pay_type == 'alipay':
        return "ALIPAYWAP", '41'
    elif pay_type == 'jd':
        return "JDWAP", '61'
    elif pay_type == 'quick':
        return "QUICK", '20'
    else:
        return "QQWAP", '51'


def create_charge(pay, pay_amount, info):
    ''' 创建订单 '''
    charge_resp = {}
    service = info['service']
    bankCode, pay_type = _get_paytype_and_bankcode(service)
    app_id = info['app_id']
    api_key = _get_api_key(app_id)
    p_dict = OrderedDict((
        ('merId', app_id),
        ('merOrdId', str(pay.id)),
        ('merOrdAmt', '%.2f' % pay_amount),
        ('payType', pay_type),
        ('bankCode', bankCode),
        ('remark', 'goods'),
        ('notifyUrl', '{}/pay/api/{}/ruyipay/'.format(
            settings.NOTIFY_PREFIX, settings.NOTIFY_PATH)),
        ('returnUrl', '{}/pay/api/{}/ruyipay/'.format(
            settings.NOTIFY_PREFIX, settings.RETURN_PATH)),
        ('signType', 'MD5'),
    ))
    p_dict['signMsg'] = generate_sign(p_dict, api_key)
    gate_url = _GATEWAY.format(p_dict['merId'], p_dict['merOrdId'], p_dict['merOrdAmt'],
                               p_dict['payType'], p_dict['bankCode'], p_dict['remark'], p_dict['returnUrl'],
                               p_dict['notifyUrl'], p_dict['signMsg'])
    charge_resp.update({
        'charge_info': gate_url,
    })
    return charge_resp


def check_notify_sign(request):
    data = dict(request.POST.iteritems())
    _LOGGER.info("ruyipay notify data: %s", data)
    app_id = data['merId']
    api_key = _get_api_key(app_id)
    verify_notify_sign(data, api_key)
    pay_id = data['merOrdId']
    if not pay_id:
        _LOGGER.error("fatal error, out_trade_no not exists, data: %s" % data)
        raise ParamError('ruyipay event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    trade_status = data['tradeStatus']
    mch_id = pay.mch_id
    trade_no = data.get('sysOrdId')
    total_fee = float(data['merOrdAmt'])

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)
    if trade_status == 'success002':
        _LOGGER.info('ruyipay check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
        # async notify
        async_job.notify_mch(pay_id)


def query_charge(pay_order, app_id):
    ''' 查询订单 '''
    # prepare param
    service = pay_order.service
    pay_id = pay_order.id
    charge_resp = {}
    api_key = _get_api_key(app_id)
    p_dict = OrderedDict((
        ('merId', app_id),
        ('merOrdId', str(pay_id)),
        ('signType', 'MD5'),
        ('timeStamp', utc_to_local(pay_order.created_at).strftime('%Y%m%d%H%M%S')),
    ))
    p_dict['signMsg'] = generate_query_sign(p_dict, api_key)
    query_url = _QUERY_GATEWAY.format(p_dict['merId'], p_dict['merOrdId'], p_dict['signType'],
                                      p_dict['timeStamp'], p_dict['signMsg'])
    response = requests.get(query_url)
    if response.status_code == 200:
        data = json.loads(response.text)
        print data
        verify_query_sign(data, api_key)
        trade_status = data['tradeStatus']
        if trade_status == '002':
            trade_no = data.get('sysOrdId')
            total_fee = float(data['merOrdAmt'])
            extend = {
                'trade_status': trade_status,
                'trade_no': trade_no,
                'total_fee': total_fee
            }
            _LOGGER.info('ruyipay query order success, mch_id:%s pay_id:%s',
                         pay_order.mch_id, pay_order.id)
            res = order_db.add_pay_success(pay_order.mch_id, pay_order.id,
                                           total_fee, trade_no, extend)
            if res:
                # async notify
                async_job.notify_mch(pay_order.id)
    else:
        _LOGGER.warn('ruyipay data error, status_code: %s', response.status_code)
    return charge_resp
